youtube: ProtocolBuffers Crash Course
https://www.youtube.com/watch?v=46O73On0gyI
Protocol buffers, 略して protobuf
code: .sh
brew install protobuf
構造化されたシリアライズデータ
通信フォーマット
Extension
.proto
.protobuf
どっちでもいけそう
Scrapbox だと .protobufにしないとハイライト効かない
Pros & Cons
code: .sh
// 125Byte
[
{ "name": "Masaharu", "salary": 9000, "id": 1001 },
{ "name": "Rick", "salary": 5000, "id": 1003 },
{ "name": "Rick", "salary": 5000, "id": 1003 }
]
ちょっとでかい
HTTP 1.1 で送るならなおさら
転送と シリアライズ& デシリアライズのフットプリントを少なくしたほうが
リアルタイム性の高い通信ができる
Most Simple Protobuf
code: .protobuf
syntax = "proto3";
message Employee{
int32 id = 1;
string name = 2;
float salary = 3;
}
各行にセミコロン必要
syntax = "proto3"; は必要なおまじない
message
message <Name> { ... }
シリアライズ構造は、message で定義
プログラミング言語で言うところの、type とか data とか struct に近い
message Field
type name = <order_number>;
最後の番号はけっこう重要
json と違い、protocol buffer はシリアライズの際に圧縮されるので、
この番号がクライアント - サーバー で一致していないとデシリアライズできない
repeted
Protobuf で、Array を表現するには
repeted <type> とする
code: .protobuf
message Employees {
repeated Employee employees = 1;
}
普通は、わざわざこんな message 作らなくても repeted <type>でやれば良さげ?
ただ、2重Array とかはこの方法じゃないと無理っぽい
あと、json のトップが Array だったりする場合もこの表現方法になりそう
protoc
Protocol Buffers Compile
略して protoc
いろんな言語のソースコードを出力する
デフォルトで、js, python, cpp, go, java, phpなど
brewでインストールするのは protobuf だが、使えるようになるのはprotoc
code: .sh
# protoc <flags> <input.proto>
protoc --js_out=impoert_style=commonjs employees.proto
serializeBinary method
Protocol buffers Objectをインスタンス化して、
メソッドで読み書きしたあとは serializeBinaryメソッドでバイナリにできる
Deno の場合は Uint8Array
code: .ts
import { Employee, Employees } from "./ts/employees_pb.js";
const person = new Employee();
person.setId(1001);
person.setName("Max");
person.setSalary(1000);
const person2 = new Employee();
person2.setId(1001);
person2.setName("Max");
person2.setSalary(1000);
const person3 = new Employee();
person3.setId(1001);
person3.setName("Max");
person3.setSalary(1000);
const employees = new Employees();
console.log(employees.serializeBinary());
Employee(単数形)を serializeBinaryして Uint8Array にしても、
Typescript だと連結する手段が見つからなかった。
複数形の Employees message に List でセットしてから
serialize したら、1 つの Uint8Array (バイナリ) にできた
code: .ls
Uint8Array(45) [
10, 13, 8, 233, 7, 18, 3, 77, 97, 120, 29,
0, 0, 122, 68, 10, 13, 8, 233, 7, 18, 3,
77, 97, 120, 29, 0, 0, 122, 68, 10, 13, 8,
233, 7, 18, 3, 77, 97, 120, 29, 0, 0, 122,
68
]
ls -lh
-rw-r--r-- 1 masaharuhosomichi staff 45B Jan 21 01:29 protobuf.bin
json: 125 Byte
protobuf binary: 45 Byte
約1/3 のサイズになった!
Deserialize Binary
code: .sh
const binary = Deno.readFileSync("protobuf.bin");
const employees2 = Employees.deserializeBinary(binary);
console.log(employees2.getEmployeesList()0.getName()); protocで生成したコードからデシリアライズできる
まとめ
protoc コマンドを入れよう (brew install protobuf)
複数形の Array は repetedly
syntax = "proto3"だと required いらない (optionalだけでいい)
js / ts の場合、普通の json を作るのではなく Protobuf の writer Objectを作って、そこにセットした後に binary
に serialize する
Array系の message も定義する (じゃないと、複数形を serialize できない